package com.example.demo.client;

import com.example.demo.exception.BizException;
import com.example.demo.exception.ErrorConstants;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;

import javax.annotation.PostConstruct;
import java.io.InputStream;

/**
 * MinioUtil
 *
 * @author hao.chen
 * @date 2023/7/21 10:05
 */
//@Component
@Slf4j
public class MinioClient {

    private static final String BIZ_DESC = "[MINIO]";

    @Value("${minio.endpoint}")
    private String endpoint;
    @Value("${minio.access-key}")
    private String accessKey;
    @Value("${minio.secret-key}")
    private String secretKey;
    @Value("${minio.bucket-name}")
    private String bucketName;

    private io.minio.MinioClient minioClient;

    @PostConstruct
    public void initClient() {
        minioClient = new io.minio.MinioClient.Builder().endpoint(endpoint).credentials(accessKey, secretKey).build();
    }

    /**
     * 根据key删除OSS服务器上的文件
     *
     * @param key Bucket下的文件的路径名+文件名 如："upload/2023/01/11/cake.jpg"
     */
    public void deleteObject(String key) {
        String actionDesc = "删除文件";
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(key).build());
        } catch (Exception e) {
            log.error("[Error] {} {}<异常>", BIZ_DESC, actionDesc, e);
            throw new BizException(ErrorConstants.SERVER_INTERNAL_ERROR.format(actionDesc));
        }
    }

    /**
     * 上传文件
     *
     * @param key      文件唯一标志
     * @param is       以输入流的形式上传文件
     * @param fileName 上传文件后新文件名
     * @return String 返回的唯一MD5数字签名
     */
    public String uploadFile(String key, InputStream is, String fileName) {
        String actionDesc = "上传文件";
        try {
            minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(key).stream(is, is.available(), -1).contentType(getContentType(fileName)).build());
        } catch (Exception e) {
            log.error("[Error] {} {}<异常>", BIZ_DESC, actionDesc, e);
            throw new BizException(ErrorConstants.SERVER_INTERNAL_ERROR.format(actionDesc));
        }
        return key;
    }

    /**
     * 获取上传文件url 默认7天过期
     *
     * @param key 文件唯一标志
     * @return 文件 url
     */
    public String getUrl(String key) {
        String actionDesc = "获取文件url";
        try {
            String url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(key).method(Method.GET).build());
            String s1 = StringUtils.substringBefore(url, "?");
            return s1.replace("http://114.55.85.83:9001/voice-chat/", "https://app.whhaixue.site/voice-chat/");
        } catch (Exception e) {
            log.error("[Error] {} {}<异常>", BIZ_DESC, actionDesc, e);
            throw new BizException(ErrorConstants.SERVER_INTERNAL_ERROR.format(actionDesc));
        }
    }


    /**
     * 通过文件名判断并获取OSS服务文件上传时文件的contentType
     *
     * @param fileName 文件名
     * @return 文件的contentType
     */
    private String getContentType(String fileName) {
        return MediaTypeFactory.getMediaType(fileName).orElse(MediaType.APPLICATION_OCTET_STREAM).toString();
    }
}
